<?php
/**************************************************************************
 *
 *   Copyright 2010 American Public Media Group
 *
 *   This file is part of AIR2.
 *
 *   AIR2 is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   AIR2 is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with AIR2.  If not, see <http://www.gnu.org/licenses/>.
 *
 *************************************************************************/

/**
 * Tank
 *
 * AIR2 Metadata concerning rows in the TankSource table
 *
 * @property integer $tank_id
 * @property string $tank_uuid
 * @property integer $tank_user_id
 * @property integer $tank_prj_id
 * @property integer $tank_org_id
 * @property integer $tank_actm_id
 * @property timestap $tank_dtim
 * @property string $tank_file_name
 * @property string $tank_notes
 * @property string $tank_meta
 * @property string $tank_type
 * @property string $tank_status
 * @property integer $tank_cre_user
 * @property integer $tank_upd_user
 * @property timestamp $tank_cre_dtim
 * @property timestamp $tank_upd_dtim
 * @property User $User
 * @property Project $Project
 * @property Organization $Organization
 * @property ActivityMaster $ActivityMaster
 * @property Doctrine_Collection $TankSource
 * @property Doctrine_Collection $TankLog
 * @author rcavis
 * @package default
 */
class Tank extends AIR2_Record {
    public static $CSV_FILENAME = 'upload.csv';

    // tank types
    public static $TYPE_CSV = 'C';
    public static $TYPE_FB = 'F';

    // status of tank
    public static $STATUS_NEW = 'N'; //nothing imported to tank_source yet
    public static $STATUS_IMPORTING = 'I'; //import in progress
    public static $STATUS_IMPORTED = 'S'; //import to tank_source complete
    public static $STATUS_IMPORT_FAILED = 'F'; //import failed
    public static $STATUS_DISCRIMINATING = 'D'; //discriminator running
    public static $STATUS_DISCRIMINATED = 'T'; //discriminator finish success
    public static $STATUS_DISCRIM_ERRORS = 'E'; //discriminator finished with errors


    /**
     * Set the table columns
     */
    public function setTableDefinition() {
        $this->setTableName('tank');
        $this->hasColumn('tank_id', 'integer', 4, array(
                'primary' => true,
                'autoincrement' => true,
            ));
        $this->hasColumn('tank_uuid', 'string', 12, array(
                'fixed' => true,
                'notnull' => true,
                'unique' => true,
            ));
        $this->hasColumn('tank_user_id', 'integer', 4, array(
                'notnull' => true,
            ));
        $this->hasColumn('tank_prj_id', 'integer', 4, array(
                'notnull' => true,
                'default' => 1, //system project
            ));
        $this->hasColumn('tank_org_id', 'integer', 4, array(
                //'notnull' => true,
            ));
        $this->hasColumn('tank_actm_id', 'integer', 4, array(
                //'notnull' => true,
                //'default' => 14, //opt-in
            ));
        $this->hasColumn('tank_dtim', 'timestamp', null, array(

            ));
        $this->hasColumn('tank_file_name', 'string', 255, array(

            ));
        $this->hasColumn('tank_notes', 'string', null, array(

            ));
        $this->hasColumn('tank_meta', 'string', null, array(

            ));
        $this->hasColumn('tank_type', 'string', 1, array(
                'fixed' => true,
                'notnull' => true,
            ));
        $this->hasColumn('tank_status', 'string', 1, array(
                'fixed' => true,
                'notnull' => true,
            ));
        $this->hasColumn('tank_cre_user', 'integer', 4, array(

            ));
        $this->hasColumn('tank_upd_user', 'integer', 4, array(

            ));
        $this->hasColumn('tank_cre_dtim', 'timestamp', null, array(
                'notnull' => true,
            ));
        $this->hasColumn('tank_upd_dtim', 'timestamp', null, array(

            ));

        parent::setTableDefinition();
    }


    /**
     * Set table relations
     */
    public function setUp() {
        parent::setUp();
        $this->hasOne('User', array(
                'local' => 'tank_user_id',
                'foreign' => 'user_id',
                'onDelete' => 'CASCADE'
            ));
        $this->hasOne('Project', array(
                'local' => 'tank_prj_id',
                'foreign' => 'prj_id',
                'onDelete' => 'CASCADE'
            ));
        $this->hasOne('Organization', array(
                'local' => 'tank_org_id',
                'foreign' => 'org_id',
                'onDelete' => 'CASCADE'
            ));
        $this->hasOne('ActivityMaster', array(
                'local' => 'tank_actm_id',
                'foreign' => 'actm_id',
                'onDelete' => 'CASCADE',
            ));
        $this->hasMany('TankSource', array(
                'local' => 'tank_id',
                'foreign' => 'tsrc_tank_id'
            ));
        $this->hasMany('TankLog', array(
                'local' => 'tank_id',
                'foreign' => 'tlog_tank_id'
            ));
    }


    /**
     * Gets the directory used for any files associated with this Tank
     *
     * @return string
     */
    public function get_folder_path() {
        return AIR2_CSV_PATH.'/upload/'.$this->tank_uuid;
    }


    /**
     * Deletes this Tank's folder, and anything in it
     */
    public function delete_folder() {
        $dir = $this->get_folder_path();
        air2_rmdir($dir);
    }


    /**
     * Gets the full filepath for this Tank's primary file, or null if this
     * type of Tank doesn't have a file.
     *
     * @return string|null
     */
    public function get_file_path() {
        if ($this->tank_type == self::$TYPE_CSV) {
            return $this->get_folder_path().'/'.self::$CSV_FILENAME;
        }
        else {
            return null;
        }
    }


    /**
     * Deletes the file associated with this tank, if it exists
     */
    public function delete_file() {
        $file = $this->get_file_path();
        if ($file && is_file($file)) {
            unlink($file);
        }
    }


    /**
     * Copies a readable file, overwriting this Tank's file.
     *
     * @param string  $source
     * @return boolean success
     */
    public function copy_file($source) {
        air2_mkdir($this->get_folder_path()); // make sure it exists
        $dest = $this->get_file_path();
        if (is_readable($source) && $dest) {
            $this->delete_file();
            copy($source, $dest);
            chmod($dest, 0770);
            return true;
        }
        return false;
    }


    /**
     * Convenience function for getting json-encoded tank_meta
     *
     * @param string  $name the meta-field name
     * @return mixed
     */
    public function get_meta_field($name) {
        if (!$this->tank_meta) {
            return null;
        }
        else {
            $data = json_decode($this->tank_meta, true);
            if (isset($data[$name])) {
                return $data[$name];
            }
            else {
                return null;
            }
        }
    }


    /**
     * Convenience function for setting json-encoded tank_meta
     *
     * @param string  $name  the meta-field name
     * @param mixed   $value the new value
     */
    public function set_meta_field($name, $value) {
        $data = array();
        if ($this->tank_meta) {
            $data = json_decode($this->tank_meta, true);
        }

        $data[$name] = $value;
        $this->tank_meta = json_encode($data);
    }


    /**
     * After a record is deleted, clean up any files/directories related to it
     *
     * @param Doctrine_Event $event
     */
    public function postDelete($event) {
        $this->delete_folder();
    }


    /**
     * Readable by owner and system.
     *
     * @param User    $user
     * @return authz integer
     */
    public function user_may_read($user) {
        if ($user->is_system()) {
            return AIR2_AUTHZ_IS_SYSTEM;
        }
        elseif ($this->tank_user_id == $user->user_id) {
            return AIR2_AUTHZ_IS_OWNER;
        }
        else {
            return AIR2_AUTHZ_IS_DENIED;
        }
    }


    /**
     * Writable by owner and system.
     *
     * @param User    $user
     * @return authz integer
     */
    public function user_may_write($user) {
        return $this->user_may_read($user);
    }


    /**
     * Manageable by owner and system.
     *
     * @param User    $user
     * @return authz integer
     */
    public function user_may_manage($user) {
        return $this->user_may_write($user);
    }


    /**
     * Restrict to owning user.
     *
     * @param AIR2_Query $q     (reference)
     * @param User    $u     (reference)
     * @param string  $alias (optional)
     */
    public static function query_may_read(AIR2_Query &$q, User &$u, $alias=null) {
        if ($u->is_system()) {
            return;
        }
        $a = ($alias) ? "$alias." : "";
        $q->addWhere("${a}tank_user_id = ?", $u->user_id);
    }


}
